﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
using Go;

namespace fhs
{
    partial class VisionParamForm_Mark : Form
    {
        Vision_Mark.Param _param;
        generator _aciton;
        Vision_Mark.Result _lastResult;
        bool _refresh;

        public VisionParamForm_Mark()
        {
            InitializeComponent();
        }

        private void VisionParamForm_Load(object sender, EventArgs e)
        {
            try
            {
                ReLoad();
            }
            catch (System.Exception ex)
            {
                LogMgr.Error($"视觉参数填充错误{ex.Message}");
            }
            generator.go(out _aciton, GlobalData.mainStrand, RefreshAction);
        }

        protected virtual VisionName.Vision Vision
        {
            get
            {
                return VisionName.Vision.Mark;
            }
        }

        private void ReLoad()
        {
            _param = (Vision_Mark.Param)VisionMgr.visionParams[Vision];
            comboBox_Mark.Items.Clear();
            foreach (var item in _param.VisionConfig)
            {
                comboBox_Mark.Items.Add(item.Key);
            }
            if (comboBox_Mark.Items.Count > 0)
            {
                comboBox_Mark.SelectedIndex = 0;
            }
        }

        private async Task RefreshAction()
        {
            while (true)
            {
                int idx = comboBox_Mark.SelectedIndex;
                await generator.sleep(100);
                if (!Visible || !Enabled || !checkBox_Refresh.Checked || idx < 0 || null == VisionDebugForm.obj.LastImage)
                {
                    continue;
                }
                VisionName.Camera camera = StringToEnum.Convert<VisionName.Camera>(comboBox_Mark.Text);
                _refresh = true;
                _lastResult = (Vision_Mark.Result)await VisionMgr.visions[Vision].Translate(VisionDebugForm.obj.CameraView, VisionDebugForm.obj.ObjectsPreview, _param, new Vision_Mark.Option { camera = camera, image = VisionDebugForm.obj.LastImage });
                _refresh = false;
                button_SelectHeng.Enabled = button_SelectShu.Enabled = null != _lastResult && _lastResult.markOK;
            }
        }

        private void VisionParamForm_Mark_FormClosing(object sender, FormClosingEventArgs e)
        {
            _aciton?.stop();
        }

        private Vision_Mark.Param.Mark CurrCamera
        {
            get
            {
                int idx = comboBox_Mark.SelectedIndex;
                if (idx < 0)
                {
                    return new Vision_Mark.Param.Mark();
                }
                VisionName.Camera camera = StringToEnum.Convert<VisionName.Camera>(comboBox_Mark.Text);
                return _param.VisionConfig[camera];
            }
        }

        private void numericUpDown_ROIRow_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.roi.Row = (double)numericUpDown_ROIRow.Value;
        }

        private void numericUpDown_ROICol_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.roi.Col = (double)numericUpDown_ROICol.Value;
        }

        private void numericUpDown_ROILen1_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.roi.Len1 = (double)numericUpDown_ROILen1.Value;
        }

        private void numericUpDown_ROILen2_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.roi.Len2 = (double)numericUpDown_ROILen2.Value;
        }

        private void numericUpDown_ROIPhi_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.roi.Phi = FlatCalib.ToRad((double)numericUpDown_ROIPhi.Value);
        }

        private void numericUpDown_Score_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.score = (double)numericUpDown_Score.Value;
        }

        private void numericUpDown_ExposureTime_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.exposureTime = (int)numericUpDown_ExposureTime.Value;
        }

        private void numericUpDown_OffsetRow_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.offsetRow = (double)numericUpDown_OffsetRow.Value;
        }

        private void numericUpDown_OffsetCol_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.offsetCol = (double)numericUpDown_OffsetCol.Value;
        }

        private void button_SelectROI_Click(object sender, EventArgs e)
        {
            if (_refresh) return;
            Enabled = false;
            VisionDebugForm.obj.DrawRectangle2(numericUpDown_ROIRow, numericUpDown_ROICol, numericUpDown_ROIPhi, numericUpDown_ROILen1, numericUpDown_ROILen2);
            Enabled = true;
        }

        private void button_DrawMark_Click(object sender, EventArgs e)
        {
            if (_refresh || null == VisionDebugForm.obj.LastImage)
            {
                return;
            }
            Enabled = false;
            double row1, col1, row2, col2;
            bool ok = VisionDebugForm.obj.DrawRectangle1(out row1, out col1, out row2, out col2);
            Enabled = true;
            if (!ok)
            {
                return;
            }
            try
            {
                HObject markImage;
                HOperatorSet.CropPart(VisionDebugForm.obj.LastImage, out markImage, row1, col1, col2 - col1 + 1, row2 - row1 + 1);
                CurrCamera.markImage = markImage;
            }
            catch (Exception)
            {
                LogMgr.Error("框选Mark出错");
            }
        }

        private void radioButton_Sharp_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton_Sharp.Checked)
            {
                CurrCamera.matchType = 0;
            }
        }

        private void radioButton_NCC_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton_NCC.Checked)
            {
                CurrCamera.matchType = 1;
            }
        }

        private void checkBox_EnableLine_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.enableLine = checkBox_EnableLine.Checked;
            groupBox_EnableLine.Enabled = checkBox_EnableLine.Checked;
        }

        private void numericUpDown_HengRow_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.hengLine.Row = (double)numericUpDown_HengRow.Value;
        }

        private void numericUpDown_HengCol_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.hengLine.Col = (double)numericUpDown_HengCol.Value;
        }

        private void numericUpDown_HengLen1_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.hengLine.Len1 = (double)numericUpDown_HengLen1.Value;
        }

        private void numericUpDown_HengLen2_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.hengLine.Len2 = (double)numericUpDown_HengLen2.Value;
        }

        private void numericUpDown_HengPhi_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.hengLine.Phi = FlatCalib.ToRad((double)numericUpDown_HengPhi.Value);
        }

        private void numericUpDown_ShuRow_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.shuLine.Row = (double)numericUpDown_ShuRow.Value;
        }

        private void numericUpDown_ShuCol_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.shuLine.Col = (double)numericUpDown_ShuCol.Value;
        }

        private void numericUpDown_ShuLen1_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.shuLine.Len1 = (double)numericUpDown_ShuLen1.Value;
        }

        private void numericUpDown_ShuLen2_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.shuLine.Len2 = (double)numericUpDown_ShuLen2.Value;
        }

        private void numericUpDown_ShuPhi_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.shuLine.Phi = FlatCalib.ToRad((double)numericUpDown_ShuPhi.Value);
        }

        private void numericUpDown_Threshold_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.threshold = (int)numericUpDown_Threshold.Value;
        }

        private void numericUpDown_Sigma_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.sigma = (double)numericUpDown_Sigma.Value;
        }

        private void numericUpDown_DeltaAngle_ValueChanged(object sender, EventArgs e)
        {
            CurrCamera.deltaAngle = FlatCalib.ToRad((double)numericUpDown_DeltaAngle.Value);
        }

        private void checkBox_MetLine_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.metrologyLine = checkBox_MetLine.Checked;
        }

        private bool DrawROI(NumericUpDown numericUpDown_Row, NumericUpDown numericUpDown_Col, NumericUpDown numericUpDown_Phi, NumericUpDown numericUpDown_Len1, NumericUpDown numericUpDown_Len2)
        {
            var srcRow = numericUpDown_Row.Value;
            var srcCol = numericUpDown_Col.Value;
            var srcPhi = numericUpDown_Phi.Value;
            var srcLen1 = numericUpDown_Len1.Value;
            var srcLen2 = numericUpDown_Len2.Value;
            try
            {
                double row, col, phi, len1, len2;
                Enabled = false;
                bool ok = VisionDebugForm.obj.DrawRectangle2(out row, out col, out phi, out len1, out len2);
                if (!ok)
                {
                    return false;
                }
                HTuple homMat;
                HOperatorSet.HomMat2dIdentity(out homMat);
                if (null != _lastResult && _lastResult.markOK)
                {
                    HOperatorSet.HomMat2dTranslate(homMat, -_lastResult.mark.Row, -_lastResult.mark.Col, out homMat);
                }
                HTuple transRow, transCol;
                HOperatorSet.AffineTransPoint2d(homMat, row, col, out transRow, out transCol);
                numericUpDown_Row.Value = (decimal)transRow.D;
                numericUpDown_Col.Value = (decimal)transCol.D;
                numericUpDown_Len1.Value = (decimal)len1;
                numericUpDown_Len2.Value = (decimal)len2;
                numericUpDown_Phi.Value = (decimal)(FlatCalib.ToDeg(phi));
                return true;
            }
            catch (System.Exception)
            {
                numericUpDown_Row.Value = srcRow;
                numericUpDown_Col.Value = srcCol;
                numericUpDown_Phi.Value = srcPhi;
                numericUpDown_Len1.Value = srcLen1;
                numericUpDown_Len2.Value = srcLen2;
                return false;
            }
            finally
            {
                Enabled = true;
            }
        }

        private void button_SelectHeng_Click(object sender, EventArgs e)
        {
            if (_refresh) return;
            Enabled = false;
            DrawROI(numericUpDown_HengRow, numericUpDown_HengCol, numericUpDown_HengPhi, numericUpDown_HengLen1, numericUpDown_HengLen2);
            Enabled = true;
        }

        private void button_SelectShu_Click(object sender, EventArgs e)
        {
            if (_refresh) return;
            Enabled = false;
            DrawROI(numericUpDown_ShuRow, numericUpDown_ShuCol, numericUpDown_ShuPhi, numericUpDown_ShuLen1, numericUpDown_ShuLen2);
            Enabled = true;
        }

        private void comboBox_Mark_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                int idx = comboBox_Mark.SelectedIndex;
                if (idx < 0) return;
                VisionName.Camera cameraName = StringToEnum.Convert<VisionName.Camera>(comboBox_Mark.Text);
                ((Vision_Mark)VisionMgr.visions[Vision]).PreviewCamera = cameraName;
                Vision_Mark.Param.Mark curr = _param.VisionConfig[cameraName];
                numericUpDown_ExposureTime.Value = (decimal)curr.exposureTime;
                numericUpDown_Score.Value = (decimal)curr.score;
                numericUpDown_OffsetRow.Value = (decimal)curr.offsetRow;
                numericUpDown_OffsetCol.Value = (decimal)curr.offsetCol;
                numericUpDown_ROIRow.Value = (decimal)curr.roi.Row;
                numericUpDown_ROICol.Value = (decimal)curr.roi.Col;
                numericUpDown_ROILen1.Value = (decimal)curr.roi.Len1;
                numericUpDown_ROILen2.Value = (decimal)curr.roi.Len2;
                numericUpDown_ROIPhi.Value = (decimal)FlatCalib.ToDeg(curr.roi.Phi);
                switch (curr.matchType)
                {
                    case 0:
                        radioButton_Sharp.Checked = true;
                        break;
                    case 1:
                        radioButton_NCC.Checked = true;
                        break;
                }
                checkBox_EnableLine.Checked = curr.enableLine;
                groupBox_EnableLine.Enabled = curr.enableLine;
                numericUpDown_HengRow.Value = (decimal)curr.hengLine.Row;
                numericUpDown_HengCol.Value = (decimal)curr.hengLine.Col;
                numericUpDown_HengLen1.Value = (decimal)curr.hengLine.Len1;
                numericUpDown_HengLen2.Value = (decimal)curr.hengLine.Len2;
                numericUpDown_HengPhi.Value = (decimal)FlatCalib.ToDeg(curr.hengLine.Phi);
                numericUpDown_ShuRow.Value = (decimal)curr.shuLine.Row;
                numericUpDown_ShuCol.Value = (decimal)curr.shuLine.Col;
                numericUpDown_ShuLen1.Value = (decimal)curr.shuLine.Len1;
                numericUpDown_ShuLen2.Value = (decimal)curr.shuLine.Len2;
                numericUpDown_ShuPhi.Value = (decimal)FlatCalib.ToDeg(curr.shuLine.Phi);
                numericUpDown_Threshold.Value = curr.threshold;
                numericUpDown_Sigma.Value = (decimal)curr.sigma;
                radioButton_HengPositive.Checked = curr.hengTransition;
                radioButton_HengNegative.Checked = !curr.hengTransition;
                radioButton_ShuPositive.Checked = curr.shuTransition;
                radioButton_ShuNegative.Checked = !curr.shuTransition;
                checkBox_MetLine.Checked = curr.metrologyLine;
                numericUpDown_DeltaAngle.Value = (decimal)FlatCalib.ToDeg(curr.deltaAngle);
                button_SelectHeng.Enabled = button_SelectShu.Enabled = false;
            }
            catch (Exception)
            {
                LogMgr.Error("Mark控件填充错误");
            }
        }

        private void radioButton_HengPositive_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.hengTransition = radioButton_HengPositive.Checked;
        }

        private void radioButton_HengNegative_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.hengTransition = !radioButton_HengNegative.Checked;
        }

        private void radioButton_ShuPositive_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.shuTransition = radioButton_ShuPositive.Checked;
        }

        private void radioButton_ShuNegative_CheckedChanged(object sender, EventArgs e)
        {
            CurrCamera.shuTransition = !radioButton_ShuNegative.Checked;
        }
    }
}
